package com.jgzx.redis.bill;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.jgzx.exception.BizException;
import com.jgzx.redis.config.CacheKeyEnum;
import com.jgzx.redis.config.RedisEnum;
import com.jgzx.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;

/**
 * @author jackesy
 * @className: CodeGenerator
 * @description: 编号生成器
 * @create 2021/3/21 22:19
 **/
@Component
public class CodeGenerator {

    private static CodeGenerator codeGenerator;

    @Autowired
    private RedisService redisService;

    @PostConstruct
    public void init() {
        codeGenerator = this;
        codeGenerator.redisService = this.redisService;
    }

    private static final String BILL_DATE_FORMAT = "yyMMdd";//单据日期长度yyMMdd
    private static final int BILL_DATE_LENGTH = 6;//单据日期长度yyMMdd
    private static final int BILL_SERIAL_NUM_MIN_LENGTH = 3;//单据编码流水号最小长度
    private static final int BIZ_SERIAL_NUM_MIN_LENGTH = 3;//业务编码流水号最小长度
    private static final int SERIAL_INCREMENT_STEP = 1;//流水号递增步长
    /**
     * @author jackesy
     * @methodName: generateBillCode
     * @description: 生成单据编码
     * @create 2021/3/21 22:24
     **/
    public static String generateBillCode(BillCodeEnum billCodeEnum, Long enterprise_id){
        if(billCodeEnum ==null){
            throw new BizException("单据类别不能为空");
        }
        String code_prefix = billCodeEnum.getValue();
        String today_date = DateUtil.format(new Date(), BILL_DATE_FORMAT);
        //缓存key：前缀+租户ID
        String cache_key = CacheKeyEnum.BILL_CODE_KEY.getValue() + code_prefix + ":" + enterprise_id;
        //获取上一个单据编号
        String last_bill_code = codeGenerator.redisService.get(RedisEnum.BIZ_CODE, cache_key);
        int serial_num = 1;
        //1、生成编号末尾的流水号
        if(StrUtil.isNotEmpty(last_bill_code)){
            String last_date = StrUtil.sub(last_bill_code, code_prefix.length(), code_prefix.length() + BILL_DATE_LENGTH);
            //上一个编码的生成日期为当天，流水号就递增
            if(last_date.equals(today_date)){
                String last_num_str = StrUtil.sub(last_bill_code, code_prefix.length() + BILL_DATE_LENGTH, last_bill_code.length());
                int last_num = Integer.parseInt(last_num_str);
                serial_num = last_num + SERIAL_INCREMENT_STEP;
            }
        }
        // 流水号不足3位左边用0补位
        String serial_num_str = String.format("%0" + BILL_SERIAL_NUM_MIN_LENGTH + "d", serial_num);
        //2、编号生成规则：前缀(4位)+日期(6位)+流水号(至少3位)，总共至少13位长度
        StringBuffer bill_code_sb = new StringBuffer();
        bill_code_sb.append(code_prefix).append(today_date).append(serial_num_str);
        String bill_code = bill_code_sb.toString();
        //3、将生成的编号缓存到redis
        codeGenerator.redisService.set(RedisEnum.BIZ_CODE, cache_key, bill_code, 0);
        return bill_code;
    }

    /**
     * @author jackesy
     * @methodName: generateBizCode
     * @description: 生成业务编码
     * @create 2021/3/21 22:24
     **/
    public static String generateBizCode(BizCodeEnum bizCodeEnum, Long enterprise_id){
        if(bizCodeEnum ==null){
            throw new BizException("业务类别不能为空");
        }
        String code_prefix = bizCodeEnum.getValue();
        //缓存key：前缀+租户ID
        String cache_key = CacheKeyEnum.BIZ_CODE_KEY.getValue() + code_prefix;
        if (ObjectUtil.isNotNull(enterprise_id)) {
            cache_key = cache_key + ":" + enterprise_id;
        }
        //获取上一个单据编号
        String last_biz_code = codeGenerator.redisService.get(RedisEnum.BIZ_CODE, cache_key);
        int serial_num = 1;
        //1、生成编号末尾的流水号
        if(StrUtil.isNotEmpty(last_biz_code)){
            String last_num_str = StrUtil.sub(last_biz_code, code_prefix.length(), last_biz_code.length());
            int last_num = Integer.parseInt(last_num_str);
            serial_num = last_num + SERIAL_INCREMENT_STEP;
        }
        // 流水号不足3位左边用0补位
        String serial_num_str = String.format("%0" + BIZ_SERIAL_NUM_MIN_LENGTH + "d", serial_num);
        //2、编号生成规则：前缀(2位)+流水号(至少3位)，总共至少5位长度
        StringBuffer biz_code_sb = new StringBuffer();
        biz_code_sb.append(code_prefix).append(serial_num_str);
        String biz_code = biz_code_sb.toString();
        //3、将编号添加到redis
        codeGenerator.redisService.set(RedisEnum.BIZ_CODE, cache_key, biz_code, 0);
        return biz_code;
    }


}
